﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using ERP.ERPSystem.ProductionSystem.Dto;
using ERP.Team.ProductionSystem;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace ERP.ERPSystem.ProductionSystem
{
    /// <summary>
    /// 生产废料服务类
    /// </summary>
    public class ProductionWasteOrderService : ApplicationService, IProductionWasteOrderService
    {
        /// <summary>
        /// 服务费聊仓储
        /// </summary>
        private readonly IRepository<ProductionWasteOrder, int> _productionWasteOrderRepository;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="productionWasteOrderRepository">服务费聊仓储</param>
        public ProductionWasteOrderService(IRepository<ProductionWasteOrder, int> productionWasteOrderRepository)
        {
            _productionWasteOrderRepository = productionWasteOrderRepository;
        }

        /// <summary>
        /// 异步获取生产废料单列表，并支持筛选、分页和排序功能
        /// </summary>
        /// <param name="input">包含筛选条件、分页和排序参数的输入DTO</param>
        /// <returns>包含分页信息和生产废料单DTO列表的分页结果对象</returns>
        public async Task<PagedResultDto<ProductionWasteOrderDto>> GetListAsync(GetProductionWasteOrderInputDto input)
        {
            // 从仓储中获取可查询的IQueryable对象，用于后续的筛选、排序和分页操作
            var query = await _productionWasteOrderRepository.GetQueryableAsync();

            // === 应用筛选条件 ===
            // 1. 根据废料单编号进行前缀匹配筛选
            // 从输入DTO中获取废料单编号筛选条件
            var wasteOrderCodeFilter = input.WasteOrderCode;
            // 检查筛选条件是否为空或仅包含空白字符
            if (!string.IsNullOrWhiteSpace(wasteOrderCodeFilter))
            {
                // 如果不为空，则在查询中添加按废料单编号前缀匹配的筛选条件
                query = query.Where(x => x.WasteOrderCode.StartsWith(wasteOrderCodeFilter));
            }

            // 2. 根据废料单名称进行包含匹配筛选
            // 从输入DTO中获取废料单名称筛选条件
            var wasteOrderNameFilter = input.WasteOrderName;
            // 检查筛选条件是否为空或仅包含空白字符
            if (!string.IsNullOrWhiteSpace(wasteOrderNameFilter))
            {
                // 如果不为空，则在查询中添加按废料单名称包含匹配的筛选条件
                query = query.Where(x => x.WasteOrderName.Contains(wasteOrderNameFilter));
            }

            // 获取应用筛选条件后的总记录数，用于分页计算
            var totalCount = await AsyncExecuter.CountAsync(query);

            // === 处理分页参数 ===
            // 确保页码是有效的正数，如果输入的页码小于等于0，则默认使用第1页
            var page = input.Page > 0 ? input.Page : 1;
            // 确保每页大小是有效的正数，如果输入的每页大小小于等于0，则默认每页显示10条记录
            var limit = input.Limit > 0 ? input.Limit : 10;
            // 根据页码和每页大小计算要跳过的记录数
            var skipCount = (page - 1) * limit;

            // === 应用排序和分页查询 ===
            // 执行查询，按更新时间降序排序，跳过指定数量的记录，获取指定数量的记录，并将结果转换为列表
            var entities = await AsyncExecuter.ToListAsync(
                query.OrderByDescending(x => x.UpdateTime) // 按更新时间降序排序
                     .Skip(skipCount)                     // 跳过指定数量的记录
                     .Take(limit)                         // 获取指定数量的记录
            );

            // 使用AutoMapper将数据库实体列表映射到数据传输对象（DTO）列表
            var dtos = ObjectMapper.Map<List<ProductionWasteOrder>, List<ProductionWasteOrderDto>>(entities);

            // 返回包含总数和当前页数据的分页结果对象
            return new PagedResultDto<ProductionWasteOrderDto>(totalCount, dtos);
        }

        /// <summary>
        /// 异步创建一个新的生产废料单
        /// </summary>
        /// <param name="input">包含新废料单信息的DTO</param>
        /// <returns>创建成功后的生产废料单DTO</returns>
        public async Task<ProductionWasteOrderDto> CreateAsync(CreateUpdateProductionWasteOrderDto input)
        {
            // 1. 使用 AutoMapper 将输入的DTO映射到数据库实体 (ProductionWasteOrder)
            var entity = ObjectMapper.Map<CreateUpdateProductionWasteOrderDto, ProductionWasteOrder>(input);
            var nowtime = DateTime.Now;

            // 2. 为新实体设置创建时间和初始更新时间
            entity.CreateTime = nowtime;
            entity.UpdateTime = nowtime;

            // 3. 将新实体异步插入到数据库并自动保存更改
            var newEntity = await _productionWasteOrderRepository.InsertAsync(entity, autoSave: true);

            // 4. 将插入后、带有新生成ID的实体映射回DTO，并返回给调用者
            return ObjectMapper.Map<ProductionWasteOrder, ProductionWasteOrderDto>(newEntity);
        }

        /// <summary>
        /// 异步更新一个已存在的生产废料单
        /// </summary>
        /// <param name="id">要更新的废料单ID</param>
        /// <param name="input">包含更新后信息的DTO</param>
        /// <returns>更新成功后的生产废料单DTO</returns>
        public async Task<ProductionWasteOrderDto> UpdateAsync(int id, CreateUpdateProductionWasteOrderDto input)
        {
            // 1. 根据ID从数据库异步获取需要更新的实体
            var entity = await _productionWasteOrderRepository.GetAsync(id);
            if (entity == null)
            {
                // 2. 如果实体不存在，则抛出一个对用户友好的异常
                throw new UserFriendlyException("更新的废料单不存在");
            }

            // 3. 使用 AutoMapper 将输入DTO的属性值更新到从数据库中取出的实体上
            ObjectMapper.Map(input, entity);
            // 4. 更新实体的"更新时间"字段
            entity.UpdateTime = DateTime.Now;

            // 5. 将更新后的实体异步更新到数据库并自动保存更改
            await _productionWasteOrderRepository.UpdateAsync(entity, autoSave: true);
            
            // 6. 将更新后的实体映射回DTO，并返回给调用者
            return ObjectMapper.Map<ProductionWasteOrder, ProductionWasteOrderDto>(entity);
        }

        /// <summary>
        /// 异步删除一个生产废料单
        /// </summary>
        /// <param name="id">要删除的废料单ID</param>
        public async Task DeleteAsync(int id)
        {
            // 根据ID从数据库中直接删除实体
            await _productionWasteOrderRepository.DeleteAsync(id);
        }
    }
}
